package com.iuhao.web.core.validation;


import com.iuhao.web.core.constants.Constants;
import com.iuhao.web.core.constants.RegExpression;
import com.iuhao.web.core.exception.CommonDefinedException;
import com.iuhao.web.core.exception.IdcardVerifyFailedException;
import com.iuhao.web.core.exception.ValidationFailedException;


import com.iuhao.web.core.utils.IdcardUtils;
import org.springframework.util.StringUtils;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * Created by Evan on 2016/5/17.
 */
public class O2OValidator {

    /**
     * 验证密码有效性
     *
     * @param password
     * @throws ValidationFailedException
     */
    public static void validatePassword(String password) throws ValidationFailedException {
        if (StringUtils.isEmpty(password)) {
            throw new ValidationFailedException(CommonDefinedException.ERROR_PASSWORD_NOT_NULL.getMessage());
        }
    }


    public static void validateChineseName(String name) throws Exception {

        if (StringUtils.isEmpty(name) || !name.matches(RegExpression.REG_CHINESE_NAME) || name.length() < 2 || name.length() > 30) {
            throw new ValidationFailedException("请输入2到30个的有效中文汉字");
        }

    }


    /**
     * 验证手机号码有效性
     *
     * @param mobile
     * @throws ValidationFailedException
     */
    public static void validateMobile(String mobile) throws ValidationFailedException {

        if (!StringUtils.isEmpty(mobile) && !mobile.matches(RegExpression.REG_MOBILE)) {
            throw new ValidationFailedException(CommonDefinedException.ERROR_WRONG_MOBILE_FORMAT.getMessage());
        }
    }

    /**
     * 验证邮箱有效性
     *
     * @param email
     * @throws ValidationFailedException
     */
    public static void validateEmail(String email) throws ValidationFailedException {

        if (!StringUtils.isEmpty(email) && !email.matches(RegExpression.REG_EMAIL)) {
            throw new ValidationFailedException(CommonDefinedException.ERROR_WRONG_EMAIL_FORMAT.getMessage());
        }
    }

    /**
     * 校验银行卡号有效性
     *
     * @param cardNumber
     * @throws ValidationFailedException
     */
    public static void validateBankCard(String cardNumber) throws ValidationFailedException {

        if (!StringUtils.isEmpty(cardNumber) && !checkBankCard(cardNumber)) {
            throw new ValidationFailedException(CommonDefinedException.ERROR_INVALID_CARD.getMessage());
        }
    }


    /**
     * 校验银行卡卡号
     *
     * @param cardId
     * @return
     */
    private static boolean checkBankCard(String cardId) throws ValidationFailedException {
        char bit = getBankCardCheckCode(cardId.substring(0, cardId.length() - 1));
        return cardId.charAt(cardId.length() - 1) == bit;
    }

    /**
     * 从不含校验位的银行卡卡号采用 Luhm 校验算法获得校验位
     *
     * @param nonCheckCodeCardId
     * @return
     */
    private static char getBankCardCheckCode(String nonCheckCodeCardId) throws ValidationFailedException {
        if (nonCheckCodeCardId == null || nonCheckCodeCardId.trim().length() == 0
            || !nonCheckCodeCardId.matches("\\d+")) {
            throw new ValidationFailedException("银行卡号必须是数字！");
        }
        char[] chs = nonCheckCodeCardId.trim().toCharArray();
        int luhmSum = 0;
        for (int i = chs.length - 1, j = 0; i >= 0; i--, j++) {
            int k = chs[i] - '0';
            if (j % 2 == 0) {
                k *= 2;
                k = k / 10 + k % 10;
            }
            luhmSum += k;
        }
        return (luhmSum % 10 == 0) ? '0' : (char) ((10 - luhmSum % 10) + '0');
    }

    /**
     * 校验身份证号码并且验证身份证是否符合贷款条件
     *
     * @param idcard
     * @throws Exception
     */
    public static void validateIdcard(String idcard) throws Exception {

        IdcardUtils.validateCard(idcard.trim());

        // 男性 20--60周岁（到还款期结束）；女性 20--55周岁（到还款期结束）
        int age = IdcardUtils.getReallyAgeByIdCard(idcard);
        if (IdcardUtils.getGenderByIdCard(idcard).equals("男")) {
            if (age < 20 || age > 60) {
                throw new IdcardVerifyFailedException(Constants.OrderFailedReason.AGE_NOT_MATCHES.getName(), "您的年龄不符合贷款要求");
            }
        } else {
            if (age < 20 || age > 55) {
                throw new IdcardVerifyFailedException(Constants.OrderFailedReason.AGE_NOT_MATCHES.getName(), "您的年龄不符合贷款要求");
            }
        }

    }

    /**
     * 验证实体类
     *
     * @param t
     * @param <T>
     * @throws Exception
     */
    public static <T> void validateModel(T t) throws Exception {
        List<String> validateError = new ArrayList<>();
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(t);
        for (ConstraintViolation<T> c : constraintViolations) {
            validateError.add(c.getMessage());
        }

        if (!validateError.isEmpty()) {
            throw new ValidationFailedException(validateError.get(0));
        }
    }

}
